package config

import (
	"database/sql"
	"encoding/xml"
	"fmt"
	"gobatis/errors"
	"gobatis/logger"
	"io/ioutil"
	"reflect"
	"strings"
)

// Configuration 框架配置
type Configuration struct {
	DataSource   *DataSource
	MapperConfig *MapperConfig
	Plugins      []interface{} // Plugin interfaces from plugins package
	Logger       logger.Interface
	ResultTypes  map[string]reflect.Type // 自定义结果类型映射
}

// DataSource 数据源配置
type DataSource struct {
	DriverName     string
	DataSourceName string
	DB             *sql.DB
}

// MapperConfig Mapper 配置
type MapperConfig struct {
	Mappers map[string]*MapperStatement
}

// MapperStatement SQL 语句配置
type MapperStatement struct {
	ID            string
	SQL           string
	ResultType    reflect.Type
	StatementType StatementType
}

// StatementType SQL 语句类型
type StatementType int

const (
	SELECT StatementType = iota
	INSERT
	UPDATE
	DELETE
)

// NewConfiguration 创建新的配置
func NewConfiguration() *Configuration {
	return &Configuration{
		MapperConfig: &MapperConfig{
			Mappers: make(map[string]*MapperStatement),
		},
		Plugins:     make([]interface{}, 0),
		Logger:      logger.Default,
		ResultTypes: make(map[string]reflect.Type),
	}
}

// SetDataSource 设置数据源
func (c *Configuration) SetDataSource(driverName, dataSourceName string) error {
	db, err := sql.Open(driverName, dataSourceName)
	if err != nil {
		return errors.NewDatabaseError("failed to open database", err).
			WithContext("driverName", driverName).
			WithContext("dataSourceName", dataSourceName)
	}

	if err := db.Ping(); err != nil {
		return errors.NewDatabaseError("failed to ping database", err).
			WithContext("driverName", driverName).
			WithContext("dataSourceName", dataSourceName)
	}

	c.DataSource = &DataSource{
		DriverName:     driverName,
		DataSourceName: dataSourceName,
		DB:             db,
	}

	return nil
}

// AddMapperXML 添加 Mapper XML 配置
func (c *Configuration) AddMapperXML(xmlPath string) error {
	data, err := ioutil.ReadFile(xmlPath)
	if err != nil {
		return errors.NewXMLParseError("failed to read mapper xml", err).
			WithContext("xmlPath", xmlPath)
	}

	var mapper XMLMapper
	if err := xml.Unmarshal(data, &mapper); err != nil {
		return errors.NewXMLParseError("failed to parse mapper xml", err).
			WithContext("xmlPath", xmlPath)
	}

	// 验证 XML 配置
	if err := c.validateXMLMapper(&mapper); err != nil {
		return errors.Wrap(errors.XMLValidationError, "invalid mapper xml", err).
			WithContext("xmlPath", xmlPath).
			WithContext("namespace", mapper.Namespace)
	}

	// 解析 select 语句
	for _, sel := range mapper.Selects {
		statementId := mapper.Namespace + "." + sel.ID
		resultType, err := c.parseResultType(sel.ResultType)
		if err != nil {
			return fmt.Errorf("failed to parse result type for %s: %w", statementId, err)
		}

		c.MapperConfig.Mappers[statementId] = &MapperStatement{
			ID:            statementId,
			SQL:           strings.TrimSpace(sel.SQL),
			ResultType:    resultType,
			StatementType: SELECT,
		}
	}

	// 解析 insert 语句
	for _, ins := range mapper.Inserts {
		statementId := mapper.Namespace + "." + ins.ID
		c.MapperConfig.Mappers[statementId] = &MapperStatement{
			ID:            statementId,
			SQL:           strings.TrimSpace(ins.SQL),
			StatementType: INSERT,
		}
	}

	// 解析 update 语句
	for _, upd := range mapper.Updates {
		statementId := mapper.Namespace + "." + upd.ID
		c.MapperConfig.Mappers[statementId] = &MapperStatement{
			ID:            statementId,
			SQL:           strings.TrimSpace(upd.SQL),
			StatementType: UPDATE,
		}
	}

	// 解析 delete 语句
	for _, del := range mapper.Deletes {
		statementId := mapper.Namespace + "." + del.ID
		c.MapperConfig.Mappers[statementId] = &MapperStatement{
			ID:            statementId,
			SQL:           strings.TrimSpace(del.SQL),
			StatementType: DELETE,
		}
	}

	return nil
}

// AddPlugin 添加插件
func (c *Configuration) AddPlugin(plugin interface{}) {
	c.Plugins = append(c.Plugins, plugin)
}

// GetMapperStatement 获取 Mapper 语句
func (c *Configuration) GetMapperStatement(statementId string) (*MapperStatement, bool) {
	stmt, exists := c.MapperConfig.Mappers[statementId]
	return stmt, exists
}

// validateXMLMapper 验证 XML Mapper 配置
func (c *Configuration) validateXMLMapper(mapper *XMLMapper) error {
	if mapper.Namespace == "" {
		return fmt.Errorf("namespace is required")
	}

	// 验证所有语句都有唯一的 ID
	ids := make(map[string]bool)

	for _, sel := range mapper.Selects {
		if sel.ID == "" {
			return fmt.Errorf("select statement id is required")
		}
		if sel.SQL == "" {
			return fmt.Errorf("select statement %s has empty SQL", sel.ID)
		}
		if ids[sel.ID] {
			return fmt.Errorf("duplicate statement id: %s", sel.ID)
		}
		ids[sel.ID] = true
	}

	for _, ins := range mapper.Inserts {
		if ins.ID == "" {
			return fmt.Errorf("insert statement id is required")
		}
		if ins.SQL == "" {
			return fmt.Errorf("insert statement %s has empty SQL", ins.ID)
		}
		if ids[ins.ID] {
			return fmt.Errorf("duplicate statement id: %s", ins.ID)
		}
		ids[ins.ID] = true
	}

	for _, upd := range mapper.Updates {
		if upd.ID == "" {
			return fmt.Errorf("update statement id is required")
		}
		if upd.SQL == "" {
			return fmt.Errorf("update statement %s has empty SQL", upd.ID)
		}
		if ids[upd.ID] {
			return fmt.Errorf("duplicate statement id: %s", upd.ID)
		}
		ids[upd.ID] = true
	}

	for _, del := range mapper.Deletes {
		if del.ID == "" {
			return fmt.Errorf("delete statement id is required")
		}
		if del.SQL == "" {
			return fmt.Errorf("delete statement %s has empty SQL", del.ID)
		}
		if ids[del.ID] {
			return fmt.Errorf("duplicate statement id: %s", del.ID)
		}
		ids[del.ID] = true
	}

	return nil
}

// parseResultType 解析结果类型
func (c *Configuration) parseResultType(resultTypeStr string) (reflect.Type, error) {
	if resultTypeStr == "" {
		// 默认使用 map[string]interface{}
		return reflect.TypeOf(map[string]interface{}{}), nil
	}

	// 处理内置类型
	switch resultTypeStr {
	case "map", "Map":
		return reflect.TypeOf(map[string]interface{}{}), nil
	case "string", "String":
		return reflect.TypeOf(""), nil
	case "int", "Int":
		return reflect.TypeOf(0), nil
	case "int64", "Int64":
		return reflect.TypeOf(int64(0)), nil
	case "float64", "Float64":
		return reflect.TypeOf(float64(0)), nil
	case "bool", "Bool":
		return reflect.TypeOf(false), nil
	default:
		// 尝试解析为类型名
		// 这里可以扩展为支持自定义类型注册
		return reflect.TypeOf(map[string]interface{}{}), nil
	}
}

// Validate 验证配置
func (c *Configuration) Validate() error {
	if c.DataSource == nil {
		return fmt.Errorf("data source is required")
	}

	if c.DataSource.DB == nil {
		return fmt.Errorf("database connection is required")
	}

	if c.MapperConfig == nil {
		return fmt.Errorf("mapper config is required")
	}

	if c.Logger == nil {
		return fmt.Errorf("logger is required")
	}

	// 验证数据库连接
	if err := c.DataSource.DB.Ping(); err != nil {
		return fmt.Errorf("database connection is not available: %w", err)
	}

	return nil
}

// RegisterResultType 注册结果类型
func (c *Configuration) RegisterResultType(name string, resultType reflect.Type) {
	if c.ResultTypes == nil {
		c.ResultTypes = make(map[string]reflect.Type)
	}
	c.ResultTypes[name] = resultType
}

// XMLMapper XML Mapper 结构
type XMLMapper struct {
	XMLName   xml.Name    `xml:"mapper"`
	Namespace string      `xml:"namespace,attr"`
	Selects   []XMLSelect `xml:"select"`
	Inserts   []XMLInsert `xml:"insert"`
	Updates   []XMLUpdate `xml:"update"`
	Deletes   []XMLDelete `xml:"delete"`
}

// XMLSelect XML Select 语句
type XMLSelect struct {
	ID         string `xml:"id,attr"`
	ResultType string `xml:"resultType,attr"`
	SQL        string `xml:",chardata"`
}

// XMLInsert XML Insert 语句
type XMLInsert struct {
	ID  string `xml:"id,attr"`
	SQL string `xml:",chardata"`
}

// XMLUpdate XML Update 语句
type XMLUpdate struct {
	ID  string `xml:"id,attr"`
	SQL string `xml:",chardata"`
}

// XMLDelete XML Delete 语句
type XMLDelete struct {
	ID  string `xml:"id,attr"`
	SQL string `xml:",chardata"`
}
